package com.chenyue.cm.base.shiro;


import com.chenyue.cm.moudules.system.service.SysMenusService;
import com.chenyue.cm.moudules.system.service.SysUsersService;
import com.chenyue.cm.system.domain.SysUsers;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.mgt.RealmSecurityManager;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.SimplePrincipalCollection;
import org.apache.shiro.subject.support.DefaultSubjectContext;
import org.crazycake.shiro.RedisSessionDAO;
import org.springframework.beans.factory.annotation.Autowired;

import javax.annotation.Resource;
import java.util.*;

/**
 * 
 * @author chenyue
 *
 */
public class MyShiroRealm extends AuthorizingRealm {

    @Resource
    private SysUsersService sysUsersService;

    @Resource
    private SysMenusService sysMenusService;

    @Autowired
    private RedisSessionDAO redisSessionDAO;

    /**
     * 授权
     *
     * @param principalCollection
     * @return
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        SysUsers sysUsers = (SysUsers) SecurityUtils.getSubject().getPrincipal();
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("sysuserid", sysUsers.getId());
        
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        
//        List<SysMenus> sysMenusList = this.sysMenusService.loadSysUserMenus(map);
//        // 权限信息对象info,用来存放查出的用户的所有的角色（role）及权限（permission）
//        for (SysMenus sysMenus : sysMenusList) {
//            info.addStringPermission(sysMenus.getPageurl());
//        }
        return info;
    }

    /**
     * 认证
     *
     * @param token
     * @return
     * @throws AuthenticationException
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        //获取用户的输入的账号.
        String username = (String) token.getPrincipal();
        String password = new String((char[]) token.getCredentials());
        SysUsers sysUsers = this.sysUsersService.selectByUsername(username);
        if (sysUsers == null) {
            throw new UnknownAccountException("账号或密码不正确");
        }
        // 密码错误
        if (!password.equals(sysUsers.getPassword())) {
            throw new IncorrectCredentialsException("账号或密码不正确");
        }
        // 账号停用校验
        if ("1".equals(sysUsers.getState())) {
            // 帐号锁定
            throw new LockedAccountException("账号已被锁定,请联系管理员");
        }
        SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(
                //用户
                sysUsers,
                //密码
                sysUsers.getPassword(),
                //realm name
                getName()
        );
        // 当验证都通过后，把用户信息放在session里
        Session session = SecurityUtils.getSubject().getSession();
        session.setAttribute("userSession", sysUsers);
        session.setAttribute("userSessionId", sysUsers.getId());
        return authenticationInfo;
    }


    /**
     * 根据userId 清除当前session存在的用户的权限缓存
     *
     * @param userIds 已经修改了权限的userId
     */
    public void clearUserAuthByUserId(List<String> userIds) {
        if (null == userIds || userIds.size() == 0) {
            return;
        }
        //获	取所有session
        Collection<Session> sessions = redisSessionDAO.getActiveSessions();
        //定义返回
        List<SimplePrincipalCollection> list = new ArrayList<SimplePrincipalCollection>();
        for (Session session : sessions) {
            //获取session登录信息。
            Object obj = session.getAttribute(DefaultSubjectContext.PRINCIPALS_SESSION_KEY);
            if (null != obj && obj instanceof SimplePrincipalCollection) {
                //强转
                SimplePrincipalCollection spc = (SimplePrincipalCollection) obj;
                //判断用户，匹配用户ID。
                obj = spc.getPrimaryPrincipal();
                if (null != obj && obj instanceof SysUsers) {
                    SysUsers sysUsers = (SysUsers) obj;
                    System.out.println("SysUsers:" + sysUsers);
                    //比较用户ID，符合即加入集合
                    if (null != sysUsers && userIds.contains(sysUsers.getId())) {
                        list.add(spc);
                    }
                }
            }
        }
        RealmSecurityManager securityManager =
                (RealmSecurityManager) SecurityUtils.getSecurityManager();
        MyShiroRealm realm = (MyShiroRealm) securityManager.getRealms().iterator().next();
        for (SimplePrincipalCollection simplePrincipalCollection : list) {
            realm.clearCachedAuthorizationInfo(simplePrincipalCollection);
        }
    }
}
